package com.game.number;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class GameController {
	Queue<Box2D> boxQueue=new LinkedList<Box2D>();
	Set<String> snapshot=new HashSet<String>();
	
	private Box2D SUCCESSFULBOX=null;
	
	private String startPos="2,2";
	
	public GameController(Box2D succ){
		this.SUCCESSFULBOX=succ;
	}
	
	public void startGame(Box2D box2d){
		
		box2d.setActivePos(startPos);

		if(box2d.equals(SUCCESSFULBOX))
			return;
		
		snapshot.add(box2d.snapshot());
		boxQueue.offer(box2d);
		
//		BoxPrinter printer=new BoxPrinter(2);
		
		do{
			Box2D box = boxQueue.poll();
//			printer.print(box);
//			System.out.println("\\\\\\\\\\\\\\");
			
			Unit activeUnit = box.findUnitByPosition(box.getActivePos());
			
			if(box.getUpUnit(activeUnit)!=null){
				Box2D upBox=box.clone();
				Unit temp=upBox.findUnitByPosition(activeUnit.getPosition());
				upBox.switchPosition(temp,upBox.getUpUnit(activeUnit));
				if(upBox.equals(SUCCESSFULBOX)){
					SUCCESSFULBOX.setParentBox2D(box);
					break;
				}
				upBox.setActivePos(temp.getPosition());
				if(!snapshot.contains(upBox.snapshot())){
					upBox.setParentBox2D(box);
					boxQueue.offer(upBox);
					snapshot.add(upBox.snapshot());
				}
			}
			
			if(box.getDownUnit(activeUnit)!=null){
				Box2D downBox=box.clone();
				Unit temp=downBox.findUnitByPosition(activeUnit.getPosition());
				downBox.switchPosition(temp,downBox.getDownUnit(activeUnit));
				if(downBox.equals(SUCCESSFULBOX)){
					SUCCESSFULBOX.setParentBox2D(box);
					break;
				}
				downBox.setActivePos(temp.getPosition());
				if(!snapshot.contains(downBox.snapshot())){
					downBox.setParentBox2D(box);
					boxQueue.offer(downBox);
					snapshot.add(downBox.snapshot());
				}
			}
			
			if(box.getLeftUnit(activeUnit)!=null){
				Box2D leftBox=box.clone();
				Unit temp=leftBox.findUnitByPosition(activeUnit.getPosition());
				leftBox.switchPosition(temp,leftBox.getLeftUnit(activeUnit));
				if(leftBox.equals(SUCCESSFULBOX)){
					SUCCESSFULBOX.setParentBox2D(box);
					break;
				}
				leftBox.setActivePos(temp.getPosition());
				if(!snapshot.contains(leftBox.snapshot())){
					leftBox.setParentBox2D(box);
					boxQueue.offer(leftBox);
					snapshot.add(leftBox.snapshot());
				}
			}
			
			if(box.getRightUnit(activeUnit)!=null){
				Box2D rightBox=box.clone();
				Unit temp=rightBox.findUnitByPosition(activeUnit.getPosition());
				rightBox.switchPosition(temp,rightBox.getRightUnit(activeUnit));
				if(rightBox.equals(SUCCESSFULBOX)){
					SUCCESSFULBOX.setParentBox2D(box);
					break;
				}
				rightBox.setActivePos(temp.getPosition());
				if(!snapshot.contains(rightBox.snapshot())){
					rightBox.setParentBox2D(box);
					boxQueue.offer(rightBox);
					snapshot.add(rightBox.snapshot());
				}
			}
			
		}while(!boxQueue.isEmpty());
		
		if(!boxQueue.isEmpty()){
			System.out.println("succ");
			
			BoxPrinter printer1=new BoxPrinter(2);
			do{
				SUCCESSFULBOX=SUCCESSFULBOX.getParentBox2D();
				printer1.print(SUCCESSFULBOX);	
				System.out.println("");
				
			}while(SUCCESSFULBOX.getParentBox2D()!=null);
			
		}else{
			System.out.println("no answer");
		}
	}
	
	public static void main(String[] args){
		String[] value=new String[]{"4","1","2","7","0","3","6","8","5"};
		String[] success=new String[]{"1","2","3","4","0","5","6","7","8"};
		
		long startTime=System.currentTimeMillis();
		
		Box2D startBox=BoxUtil.generateRandomBox2D(value);
		Box2D succBox=BoxUtil.generateRandomBox2D(success);
		
		GameController control=new GameController(succBox);
		
		control.startGame(startBox);
		
		long endTime=System.currentTimeMillis();
		
		System.out.println("During time:"+(endTime-startTime)/1000);
	}

}

